/*
 * Copyright (C) 2006-2010 - Frictional Games
 *
 * This file is part of Penumbra Overture.
 *
 * Penumbra Overture is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Penumbra Overture is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Penumbra Overture.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "GameEnemy_Spider.h"


#include "Player.h"
#include "AttackHandler.h"
#include "EffectHandler.h"
#include "GameMusicHandler.h"
#include "GameSwingDoor.h"
#include "MapHandler.h"

//////////////////////////////////////////////////////////////////////////
// BASE STATE
//////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------

iGameEnemyState_Spider_Base::iGameEnemyState_Spider_Base(int alId, cInit *apInit, iGameEnemy *apEnemy)
							: iGameEnemyState(alId,apInit,apEnemy)
{	
	mpEnemySpider = static_cast<cGameEnemy_Spider*>(mpEnemy);
}

//-----------------------------------------------------------------------

void iGameEnemyState_Spider_Base::OnSeePlayer(const cVector3f &avPosition, float afChance)
{
	if(mpPlayer->GetHealth() <=0) return;

	if(afChance >= mpEnemySpider->mfIdleMinSeeChance)
	{
		mpEnemy->ChangeState(STATE_HUNT);
		mpEnemySpider->PlaySound(mpEnemySpider->msIdleFoundPlayerSound);
	}
}

bool iGameEnemyState_Spider_Base::OnHearNoise(const cVector3f &avPosition, float afVolume)
{
	float afDistance = (mpMover->GetCharBody()->GetPosition() - avPosition).Length();

	if(afVolume >= mpEnemySpider->mfIdleMinHearVolume && afDistance > 0.4f)
	{
		//mpEnemy->SetTempPosition(avPosition);
		//mpEnemy->ChangeState(STATE_INVESTIGATE);
		return true;
	}

	return false;
}

void iGameEnemyState_Spider_Base::OnTakeHit(float afDamage)
{
	if(afDamage >= 5)
	{
		mpEnemy->ChangeState(STATE_KNOCKDOWN);
	}
}

void iGameEnemyState_Spider_Base::OnFlashlight(const cVector3f &avPosition)
{
	//mpInit->mpEffectHandler->GetSubTitle()->Add("Flashlight!",0.5f);
	//OnSeePlayer(mpPlayer->GetCharacterBody()->GetFeetPosition(),1.0f);
	if(mlId == STATE_KNOCKDOWN) return;
	
	if(mpEnemySpider->mbFleeFromFlashlight) mpEnemy->ChangeState(STATE_FLEE);
}

void iGameEnemyState_Spider_Base::OnDeath(float afDamage)
{
	mpEnemy->ChangeState(STATE_KNOCKDOWN);
	//mpEnemy->ChangeState(STATE_DEAD);
}

//-----------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////
// IDLE STATE
//////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Idle::OnEnterState(iGameEnemyState *apPrevState)
{
	//Animation
	mpEnemy->PlayAnim("Idle",false,0.2f);

	//Setup body
	mpEnemy->SetupBody();

	//Setup enemy
	mpEnemy->SetFOV(mpEnemySpider->mfIdleFOV);

	mpInit->mpMusicHandler->RemoveAttacker(mpEnemy);

	mbStopped = true;

	mfNextWalkTime = cMath::RandRectf(	mpEnemySpider->mfIdleMinWaitLength,
										mpEnemySpider->mfIdleMaxWaitLength);
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Idle::OnLeaveState(iGameEnemyState *apNextState)
{
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Idle::OnUpdate(float afTimeStep)
{
	if(mpMover->IsMoving()==false || mpMover->GetStuckCounter() > 2.0f)
	{
		mpMover->ResetStuckCounter();

		if(mbStopped==false)
		{
			mbStopped = true;

			mpEnemy->PlayAnim("Idle",false,0.9f);

			mfNextWalkTime = cMath::RandRectf(	mpEnemySpider->mfIdleMinWaitLength,
												mpEnemySpider->mfIdleMaxWaitLength);
		}
		else if(mfNextWalkTime <=0)
		{
			mbStopped = false;

			//Animation
			mpEnemy->UseMoveStateAnimations();

			//Setup body
			mpEnemy->SetupBody();
			mpMover->GetCharBody()->SetMaxPositiveMoveSpeed(eCharDir_Forward,mpEnemySpider->mfHuntSpeed);

			cAINode *pNode = NULL;
			
			if(mpEnemy->GetPatrolNodeNum()==0)
			{
				pNode = mpMover->GetAINodeInRange(	1, 5);
			}
			else
			{
				int lNodeNum = cMath::RandRectl(0,mpEnemy->GetPatrolNodeNum()-1);
				tString sName = mpEnemy->GetPatrolNode(lNodeNum)->msNodeName;
				pNode = mpMover->GetNodeContainer()->GetNodeFromName(sName);
			}
			
			if(pNode) 
			{
				mpMover->MoveToPos(pNode->GetPosition());
			}
			else
			{
				mpEnemy->ChangeState(STATE_IDLE);
			}
		}
		else
		{
			mfNextWalkTime -= afTimeStep;
		}
	}
}

//-----------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////
// HUNT STATE
//////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Hunt::OnEnterState(iGameEnemyState *apPrevState)
{
	//Animation
	mpEnemy->UseMoveStateAnimations();

	//Setup body
	float fMul = 1.0f;
	if(mpInit->mbHasHaptics) fMul = 0.6f;

	mpEnemy->SetupBody();
	if(mpInit->mDifficulty == eGameDifficulty_Easy)
		mpMover->GetCharBody()->SetMaxPositiveMoveSpeed(eCharDir_Forward,mpEnemySpider->mfHuntSpeed*0.7f*fMul);
	else if(mpInit->mDifficulty == eGameDifficulty_Normal)
		mpMover->GetCharBody()->SetMaxPositiveMoveSpeed(eCharDir_Forward,mpEnemySpider->mfHuntSpeed*fMul);
	else
		mpMover->GetCharBody()->SetMaxPositiveMoveSpeed(eCharDir_Forward,mpEnemySpider->mfHuntSpeed*1.2f*fMul);

	//Setup enemy
	mpEnemy->SetFOV(mpEnemySpider->mfHuntFOV);

	mfUpdatePathCount =0;
	mfUpdateFreq = 1.0f;
	mbFreePlayerPath = false;
	
	mbLostPlayer = false;
	mfLostPlayerCount =0;
	mfMaxLostPlayerCount = mpEnemySpider->mfHuntForLostPlayerTime;

    mpInit->mpMusicHandler->AddAttacker(mpEnemy);

	if(mpEnemySpider->mbPathFind==false) mpMover->Stop();
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Hunt::OnLeaveState(iGameEnemyState *apNextState)
{
	mpMover->SetMaxDoorToughness(-1);
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Hunt::OnUpdate(float afTimeStep)
{
	if(mpPlayer->GetHealth() <=0){
		mpEnemy->ChangeState(STATE_IDLE);
		return;
	}

	if(mpMover->GetStuckCounter() > 2.1f)
	{
		mpEnemy->ChangeState(STATE_FLEE);
		mpMover->ResetStuckCounter();
		return;
	}

	//Check if he should attack.
	if(mpMover->DistanceToChar2D(mpPlayer->GetCharacterBody()) < mpEnemySpider->mfAttackDistance)
	{
		mpEnemy->ChangeState(STATE_ATTACK);
	}
	
	if(mpEnemySpider->mbPathFind)
	{
		if(mfUpdatePathCount <=0)
		{
			mfUpdatePathCount = mfUpdateFreq;
			
			cAINodeContainer *pNodeCont = mpEnemy->GetMover()->GetNodeContainer();
			
			//Check if there is a free path to the player
			if(mbLostPlayer == false && mpMover->FreeDirectPathToChar(mpPlayer->GetCharacterBody()))
			{
				mbFreePlayerPath = true;
				mpMover->Stop();
			}
			else
			{
				mbFreePlayerPath = false;
			}
			
			//Get path to player
			if(mbFreePlayerPath==false && mbLostPlayer == false)
			{
				if(mpMover->MoveToPos(mpEnemy->GetLastPlayerPos())==false)
				{
					mfUpdatePathCount *= 5.0f;
				}
			}
		}
		else
		{
			mfUpdatePathCount -= afTimeStep;
		}
	}
	else
	{
		mbFreePlayerPath = true;

		if(mpEnemy->CanSeePlayer()==false)
		{
			mfLostPlayerCount-= afTimeStep;

			if(mfLostPlayerCount <= 0 || mpMover->GetStuckCounter()>0.5f)
			{
				mpEnemy->ChangeState(STATE_IDLE);
			}
		}
		else
		{
			mfLostPlayerCount = mfMaxLostPlayerCount*2;
		}
	}
	
	////////////////////////////////
	//Go directly towards the player
	if(mbFreePlayerPath)
	{
		//Go towards player
		mpMover->MoveDirectToPos(mpPlayer->GetCharacterBody()->GetFeetPosition(),afTimeStep);
	}
	////////////////////////////////
	//Update path search
	else
	{
		if(mbLostPlayer==false && mpMover->IsMoving()==false)
		{
			mbLostPlayer = true;
			mfLostPlayerCount = mfMaxLostPlayerCount;
		}
		
		if(mbLostPlayer)
		{
			mpMover->GetCharBody()->Move(eCharDir_Forward,1.0f,afTimeStep);
			
			mfLostPlayerCount -= afTimeStep;
			if(mfLostPlayerCount <= 0 || mpMover->GetStuckCounter()>0.5f)
			{
				mpEnemy->ChangeState(STATE_IDLE);
			}
		}
	}
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Hunt::OnSeePlayer(const cVector3f &avPosition, float afChance)
{
	if(mbLostPlayer && afChance >= mpEnemySpider->mfHuntMinSeeChance)
	{
		mbLostPlayer = false;
		mfUpdatePathCount =0;
	}
}

//-----------------------------------------------------------------------

bool cGameEnemyState_Spider_Hunt::OnHearNoise(const cVector3f &avPosition, float afVolume)
{
	//////////////////////////////////
	//If player is lost the sound might be of help
	if(mbLostPlayer)
	{
		//Check if sound can be heard
		if(afVolume >= mpEnemySpider->mfHuntMinHearVolume)
		{
			//Check if a node is found near the sound.
			cAINode *pNode = mpMover->GetAINodeAtPosInRange(avPosition,0.0f,5.0f,true, 0.1f);
			if(pNode)
			{
				//Update last player postion.
				mbLostPlayer = false;
				mfUpdatePathCount =0;
				mpEnemy->SetLastPlayerPos(pNode->GetPosition());

				return true;
			}
		}
	}
	
	return false;
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Hunt::OnDraw()
{
	//mpInit->mpDefaultFont->Draw(cVector3f(230,10,100),14,cColor(1,1,1,1),eFontAlign_Left,
	//							"Freepath: %d",mbFreePlayerPath);
}

//-----------------------------------------------------------------------


//////////////////////////////////////////////////////////////////////////
// ATTACK STATE
//////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Attack::OnEnterState(iGameEnemyState *apPrevState)
{
	//Setup body
	mpEnemy->SetupBody();
	mpMover->GetCharBody()->SetMaxPositiveMoveSpeed(eCharDir_Forward,mpEnemySpider->mfHuntSpeed);
	
	//Animation
	mpEnemy->PlayAnim("Attack",false,0.2f);

	mpEnemySpider->PlaySound(mpEnemySpider->msAttackStartSound);

	mfJumpTimer = mpEnemySpider->mfAttackJumpTime;

	mfDamageTimer = mpEnemySpider->mfAttackDamageTime;
	mbAttacked = false;
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Attack::OnLeaveState(iGameEnemyState *apNextState)
{
	//mpMover->GetCharBody()->SetForce(0);
	mpEnemySpider->SetSkipSoundTriggerCount(2.0f);
	mpMover->ResetStuckCounter();
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Attack::OnUpdate(float afTimeStep)
{
	if(mfJumpTimer >0)
	{
		mfJumpTimer -= afTimeStep;

		if(mfJumpTimer <= 0)
		{
			cVector3f vDirection =	mpInit->mpPlayer->GetCamera()->GetPosition() -
									mpMover->GetCharBody()->GetPosition();
			float fHeight = cMath::Abs(vDirection.y);
			vDirection.Normalise();
			
			cVector3f vForce = vDirection * mpEnemySpider->mfAttackForce;
			vForce.y = fHeight * 0.5f * mpEnemySpider->mfAttackForce;
			mpMover->GetCharBody()->AddForce(vForce);
		}
	}
	
	cVector3f vStart = mpPlayer->GetCharacterBody()->GetPosition();
	vStart.y =0;
	cVector3f vEnd = mpMover->GetCharBody()->GetPosition();
	vEnd.y = 0;
	float fDist2D = cMath::Vector3DistSqr(vStart,vEnd);
	float fMinRange = mpEnemySpider->mfAttackDamageRange + 0.4f;

	if(fDist2D <=  fMinRange*fMinRange && mfDamageTimer <=0)
	{
		if(mbAttacked == false)
		{
			cVector3f vPos =	mpMover->GetCharBody()->GetPosition() +
								mpMover->GetCharBody()->GetForward() * 
								mpEnemySpider->mfAttackDamageRange;

			cVector3f vRot = cVector3f(0,mpMover->GetCharBody()->GetYaw(),0);
			cMatrixf mtxOffset = cMath::MatrixRotate(vRot,eEulerRotationOrder_XYZ);
			mtxOffset.SetTranslation(vPos);
			
			eAttackTargetFlag target = eAttackTargetFlag_Player | eAttackTargetFlag_Bodies;

			mpInit->mpPlayer->mbDamageFromPos = true;
			mpInit->mpPlayer->mvDamagePos = mpMover->GetCharBody()->GetPosition();
			if(mpInit->mpAttackHandler->CreateShapeAttack(mpEnemySpider->GetAttackShape(),
										mtxOffset,
										mpMover->GetCharBody()->GetPosition(),
										cMath::RandRectf(	mpEnemySpider->mfAttackMinDamage,
															mpEnemySpider->mfAttackMaxDamage),
										
										mpEnemySpider->mfAttackMinMass, mpEnemySpider->mfAttackMaxMass,
										mpEnemySpider->mfAttackMinImpulse, mpEnemySpider->mfAttackMaxImpulse,
										
										mpEnemySpider->mlAttackStrength,

										target,NULL))
			{
				mpEnemySpider->PlaySound(mpEnemySpider->msAttackHitSound);
			}
			mpInit->mpPlayer->mbDamageFromPos = false;
			mbAttacked = true;
		}
	}
	else if(mfDamageTimer >0)
	{
		mfDamageTimer -= afTimeStep;
	}

}

void cGameEnemyState_Spider_Attack::OnFlashlight(const cVector3f &avPosition)
{
	if(mfJumpTimer >0 && mpEnemySpider->mbFleeFromFlashlight) mpEnemy->ChangeState(STATE_FLEE);
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Attack::OnAnimationOver(const tString &asName)
{
	mpEnemy->ChangeState(STATE_HUNT);
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Attack::OnPostSceneDraw()
{
	cCamera3D *pCamera = static_cast<cCamera3D*>(mpInit->mpGame->GetScene()->GetCamera());
	
	cVector3f vPos =	mpMover->GetCharBody()->GetPosition() +
						mpMover->GetCharBody()->GetForward() * 
						mpEnemySpider->mfAttackDamageRange;

	cVector3f vRot = cVector3f(0,mpMover->GetCharBody()->GetYaw(),0);
	cMatrixf mtxOffset = cMath::MatrixRotate(vRot,eEulerRotationOrder_XYZ);
	mtxOffset.SetTranslation(vPos);	
	
	
	cMatrixf mtxCollider = cMath::MatrixMul(pCamera->GetViewMatrix(),mtxOffset);

	mpInit->mpGame->GetGraphics()->GetLowLevel()->SetMatrix(eMatrix_ModelView,mtxCollider);

	cVector3f vSize = mpEnemySpider->GetAttackShape()->GetSize();
	mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawBoxMaxMin(vSize*0.5f,vSize*-0.5f,
		cColor(1,0,1,1));
}

//-----------------------------------------------------------------------


//////////////////////////////////////////////////////////////////////////
// FLEE STATE
//////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Flee::OnEnterState(iGameEnemyState *apPrevState)
{
	//Animation
	mpEnemy->UseMoveStateAnimations();

	//Setup body
	mpEnemy->SetupBody();
	mpMover->GetCharBody()->SetMaxPositiveMoveSpeed(eCharDir_Forward,mpEnemySpider->mfHuntSpeed);

	cVector3f vDir = mpMover->GetCharBody()->GetPosition() - mpPlayer->GetCharacterBody()->GetPosition();
	vDir.Normalise();
	
	cVector3f vStart = 	mpMover->GetCharBody()->GetPosition() + vDir*mpEnemySpider->mfFleeMaxDistance;

	cAINode *pNode = mpMover->GetAINodeAtPosInRange(vStart,	
													mpEnemySpider->mfFleeMinDistance, 
													mpEnemySpider->mfFleeMaxDistance,
													false,0);
	if(pNode) 
	{
		mpMover->MoveToPos(pNode->GetPosition());
	}
	else
	{
		mpEnemy->ChangeState(STATE_HUNT);
	}
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Flee::OnLeaveState(iGameEnemyState *apNextState)
{
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Flee::OnUpdate(float afTimeStep)
{
	//Move forward
	if(mpMover->IsMoving()==false || mpMover->GetStuckCounter() > 2.3f)
	{
		mpMover->ResetStuckCounter();

		if(mlPreviousState != STATE_FLEE && mlPreviousState != STATE_ATTACK)
			mpEnemy->ChangeState(mlPreviousState);
		else
			mpEnemy->ChangeState(STATE_HUNT);
	}
}

//-----------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////
// KNOCK DOWN STATE
//////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_KnockDown::OnEnterState(iGameEnemyState *apPrevState)
{
	//Animation
	mpEnemy->PlayAnim("Idle",true,0.7f);

	//Sound
	mpEnemy->PlaySound(mpEnemySpider->msKnockDownSound);

	//Setup body
	mpEnemy->SetupBody();

	//Go to rag doll
	mpEnemy->GetMeshEntity()->AlignBodiesToSkeleton(false);
	mpEnemy->GetMeshEntity()->SetSkeletonPhysicsActive(true);
	mpEnemy->GetMeshEntity()->Stop();

	mpEnemy->GetMover()->GetCharBody()->SetEntity(NULL);
	mpEnemy->GetMover()->GetCharBody()->SetActive(false);

	mpEnemy->GetMover()->Stop();

	mfTimer = 2.0f;
	mbCheckAnim = false;
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_KnockDown::OnLeaveState(iGameEnemyState *apNextState)
{
	mpEnemy->GetMover()->GetCharBody()->SetEntity(mpEnemy->GetMeshEntity());
	mpEnemy->GetMover()->GetCharBody()->SetActive(true);
	mpMover->ResetStuckCounter();
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_KnockDown::OnUpdate(float afTimeStep)
{
	if(mbCheckAnim)
	{
	}
	else
	{
		mfTimer -= afTimeStep;

		if(mfTimer <=0)
		{
			//Get the forward vector from root bone (the right vector)
			cNodeIterator StateIt = mpEnemy->GetMeshEntity()->GetRootNode()->GetChildIterator();
			cBoneState *pBoneState = static_cast<cBoneState*>(StateIt.Next());

			//Play animation and fade physics
			float fFadeTime = 0.7f;
			mbCheckAnim = true;

			mpEnemy->GetMeshEntity()->Stop();
			if(mpEnemy->GetHealth() >0)
				mpEnemy->PlayAnim("Walk",false,fFadeTime);
			else
				mpEnemy->PlayAnim("Death",false,fFadeTime);
			
			mpEnemy->GetMeshEntity()->FadeSkeletonPhysicsWeight(fFadeTime);

			//Calculate values
			cVector3f vPosition;
			cVector3f vAngles;
			cMatrixf mtxTransform = mpEnemy->GetMeshEntity()->CalculateTransformFromSkeleton(&vPosition,&vAngles);


			cVector3f vGroundPos = vPosition;
			bool bFoundGround = mpEnemy->GetGroundFinder()->GetGround(vPosition,cVector3f(0,-1,0),&vGroundPos,NULL);

			//Set body
			iCharacterBody *pCharBody = mpEnemy->GetMover()->GetCharBody();

			vGroundPos.z -= pCharBody->GetEntityOffset().GetTranslation().z;
			pCharBody->SetFeetPosition(vGroundPos);
			pCharBody->SetYaw(vAngles.y - mpEnemy->GetModelOffsetAngles().y);
			pCharBody->SetEntity(mpEnemy->GetMeshEntity());
			pCharBody->SetActive(true);

			for(int i=0; i<3; ++i)
			{
				pCharBody->Update(1.0f/60.0f);

				mpEnemy->GetMeshEntity()->UpdateLogic(1.0f/60.0f);
				mpEnemy->GetMeshEntity()->UpdateGraphics(NULL,1.0f/60.0f,NULL);
			}
			
			if(mpEnemy->GetHealth() > 0)
				mpEnemy->ChangeState(STATE_HUNT);
			else
				mpEnemy->ChangeState(STATE_DEAD);
		}
	}
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_KnockDown::OnAnimationOver(const tString &asName)
{
	if(mpEnemy->GetHealth() >0)
		mpEnemy->ChangeState(STATE_HUNT);
	else
		mpEnemy->ChangeState(STATE_DEAD);
}

//-----------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////
// DEAD STATE
//////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Dead::OnEnterState(iGameEnemyState *apPrevState)
{
	//Animation
	mpEnemy->PlayAnim("Death",false,0.7f);

	//Sound
	mpEnemy->PlaySound(mpEnemySpider->msDeathSound);

	//Setup body
	mpEnemy->SetupBody();

	mpInit->mpMusicHandler->RemoveAttacker(mpEnemy);

	//Temp:
	//mpMover->GetCharBody()->GetBody()->SetCollideCharacter(false);
	mpMover->GetCharBody()->GetBody()->SetActive(false);

	mpEnemy->GetMover()->Stop();
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Dead::OnLeaveState(iGameEnemyState *apNextState)
{
}

//-----------------------------------------------------------------------

void cGameEnemyState_Spider_Dead::OnUpdate(float afTimeStep)
{

}

//-----------------------------------------------------------------------


//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------

cGameEnemy_Spider::cGameEnemy_Spider(cInit *apInit,const tString& asName,TiXmlElement *apGameElem) : iGameEnemy(apInit,asName,apGameElem)
{
	LoadBaseProperties(apGameElem);
	
	//////////////////////////////
	//State properties
	mbPathFind = cString::ToBool(apGameElem->Attribute("PathFind"),true);

	mfIdleFOV = cMath::ToRad(cString::ToFloat(apGameElem->Attribute("IdleFOV"),0));
	msIdleFoundPlayerSound = cString::ToString(apGameElem->Attribute("IdleFoundPlayerSound"),"");
	mfIdleMinSeeChance = cString::ToFloat(apGameElem->Attribute("IdleMinSeeChance"),0);
	mfIdleMinHearVolume = cString::ToFloat(apGameElem->Attribute("IdleMinHearVolume"),0);
	mfIdleMinWaitLength = cString::ToFloat(apGameElem->Attribute("IdleMinWaitLength"),0);
	mfIdleMaxWaitLength = cString::ToFloat(apGameElem->Attribute("IdleMaxWaitLength"),0);

	mfHuntFOV = cMath::ToRad(cString::ToFloat(apGameElem->Attribute("HuntFOV"),0));
	mfHuntSpeed = cString::ToFloat(apGameElem->Attribute("HuntSpeed"),0);
	mfHuntForLostPlayerTime = cString::ToFloat(apGameElem->Attribute("HuntForLostPlayerTime"),0);
	mfHuntMinSeeChance = cString::ToFloat(apGameElem->Attribute("IdleMinSeeChance"),0);
	mfHuntMinHearVolume = cString::ToFloat(apGameElem->Attribute("IdleMinHearVolume"),0);

	mfAttackDistance = cString::ToFloat(apGameElem->Attribute("AttackDistance"),0);
	mfAttackForce = cString::ToFloat(apGameElem->Attribute("AttackForce"),0);
	mfAttackJumpTime = cString::ToFloat(apGameElem->Attribute("AttackJumpTime"),0);
	mfAttackDamageTime = cString::ToFloat(apGameElem->Attribute("AttackDamageTime"),0);
	mvAttackDamageSize = cString::ToVector3f(apGameElem->Attribute("AttackDamageSize"),0);
	mfAttackDamageRange = cString::ToFloat(apGameElem->Attribute("AttackDamageRange"),0);
	mfAttackMinDamage = cString::ToFloat(apGameElem->Attribute("AttackMinDamage"),0);
	mfAttackMaxDamage = cString::ToFloat(apGameElem->Attribute("AttackMaxDamage"),0);
	msAttackStartSound = cString::ToString(apGameElem->Attribute("AttackStartSound"),"");
	msAttackHitSound = cString::ToString(apGameElem->Attribute("AttackHitSound"),"");
	mfAttackMinMass = cString::ToFloat(apGameElem->Attribute("AttackMinMass"),0);
	mfAttackMaxMass = cString::ToFloat(apGameElem->Attribute("AttackMaxMass"),0);
	mfAttackMinImpulse = cString::ToFloat(apGameElem->Attribute("AttackMinImpulse"),0);
	mfAttackMaxImpulse = cString::ToFloat(apGameElem->Attribute("AttackMaxImpulse"),0);
	mlAttackStrength = cString::ToInt(apGameElem->Attribute("AttackStrength"),0);
	mvPreloadSounds.push_back(msAttackStartSound);
	mvPreloadSounds.push_back(msAttackHitSound);

	mfFleeMinDistance = cString::ToFloat(apGameElem->Attribute("FleeMinDistance"),0);
	mfFleeMaxDistance = cString::ToFloat(apGameElem->Attribute("FleeMaxDistance"),0);
	mbFleeFromFlashlight = cString::ToBool(apGameElem->Attribute("FleeFromFlashlight"),true);

	msKnockDownSound = cString::ToString(apGameElem->Attribute("KnockDownSound"),"");
	mvPreloadSounds.push_back(msKnockDownSound);
	
	msDeathSound = cString::ToString(apGameElem->Attribute("DeathSound"),"");
	mvPreloadSounds.push_back(msDeathSound);
	


	//////////////////////////////
	//Set up states
	AddState(hplNew( cGameEnemyState_Spider_Idle,(STATE_IDLE,mpInit,this)) );
	AddState(hplNew( cGameEnemyState_Spider_Hunt,(STATE_HUNT,mpInit,this)) );
	AddState(hplNew( cGameEnemyState_Spider_Attack,(STATE_ATTACK,mpInit,this)) );
	AddState(hplNew( cGameEnemyState_Spider_Flee,(STATE_FLEE,mpInit,this)) );
	AddState(hplNew( cGameEnemyState_Spider_KnockDown,(STATE_KNOCKDOWN,mpInit,this)) );
	AddState(hplNew( cGameEnemyState_Spider_Dead,(STATE_DEAD,mpInit,this)) );
}

//-----------------------------------------------------------------------

cGameEnemy_Spider::~cGameEnemy_Spider()
{

}

//-----------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------

void cGameEnemy_Spider::OnLoad()
{
	//Create attack shape
	iPhysicsWorld *pPhysicsWorld = mpInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld();
	mpAttackShape = pPhysicsWorld->CreateBoxShape(mvAttackDamageSize,NULL);
	
	//Set up shape
	ChangeState(STATE_IDLE);
}

//-----------------------------------------------------------------------

void cGameEnemy_Spider::OnUpdate(float afTimeStep)
{

}

//-----------------------------------------------------------------------

void cGameEnemy_Spider::ShowPlayer(const cVector3f& avPlayerFeetPos)
{
	if(	mlCurrentState == STATE_IDLE || mlCurrentState == STATE_PATROL || 
		mlCurrentState == STATE_INVESTIGATE)
	{
		mvLastPlayerPos = avPlayerFeetPos;
		ChangeState(STATE_HUNT);
	}
}

//-----------------------------------------------------------------------

bool cGameEnemy_Spider::MoveToPos(const cVector3f& avFeetPos)
{
	if(	mlCurrentState == STATE_IDLE || mlCurrentState == STATE_PATROL)
	{
		//SetTempPosition(avFeetPos);
		//ChangeState(STATE_INVESTIGATE);
		//return true;
		return false;
	}
	else
	{
		return false;
	}
	
}

//-----------------------------------------------------------------------

bool cGameEnemy_Spider::IsFighting()
{
	if( mfHealth <= 0 || IsActive()==false) return false;
	if(	mlCurrentState == STATE_IDLE || mlCurrentState == STATE_PATROL || 
		mlCurrentState == STATE_INVESTIGATE) return false;

	return true;
}

//-----------------------------------------------------------------------
